/*================================================================
*   File Name：commen.h
*   Mail: a1277992967@163.com 
*   blog: http://www.ycst.club/suggest/ 
*   Author：ycst
*   Created Time：2022年08月08日 星期一 18时41分02秒
*   Describe：公共头文件
*
================================================================*/
#ifndef _COMMON_H_
#define _COMMON_H_

#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <errno.h>
#include <time.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/epoll.h>

#define	MSL 10			//最大报文生命周期
#define	PORT 9000		//端口数
#define BUF_SIZE 200	//大小
#define HEART_TIME 60	//心跳间隔

enum {
	ERROR = -1,
	RIGHT = 0
};

#define FIN 0x01    //结束位
#define SYN	0x02    //发送位
#define ACK	0x04    //确认位
#define BIP 0x08    //校验位
#define RTO 0x10    //计时器
#define BIT 0x20    //心跳位

typedef struct Datapack{
	unsigned short seq;		//2字节	seq
	unsigned short ack;		//2字节	ack
	unsigned char check;	//1字节	验证区	0:FIN	1:SYN	2:ACK	3:BIP	4:RTO  5:BIT 
	char my_data[100];		//数据区
}Datapack;

int get_seq(char *recv_buf);
int get_ack(char *recv_buf);
int get_check(char *recv_buf);
int get_data(char *recv_buf, char *buf);
int Parity_Check(char *recv_buf);
int Parity_Create(Datapack data);


/*	
 *	Describe：校验码添加	
 *	@recv_buffer : 要添加的数据包
 */
#define BP(dat)	\
	parity = Parity_Create(dat);	\
	if(parity == 1)	dat.check |= BIP;	

/*	
 *	Describe：服务器接收差错重传
 *	@recv_buffer : 信息接收到这里
 */
#define server_error_req(recv_buffer)	\
	while(1){	\
		if(Parity_Check(recv_buffer) == RIGHT){		\
			sendto(server_id, "OK", sizeof("OK"), 0, (struct sockaddr *)&sock_client, sizeof(sock_client));	\
			break;	\
		}	\
		printf("数据错误 准备接收重传\r\n");	\
		sleep(1);	\
		sendto(server_id, "ERROR", sizeof("ERROR"), 0, (struct sockaddr *)&sock_client, sizeof(sock_client));	\
		recvfrom(server_id, recv_buffer, sizeof(recv_buffer), 0, (struct sockaddr *)&sock_client, &c_len);	\
	}
	
/*	
 *	Describe：客户端接收差错重传
 *	@recv_buffer : 信息接收到这里
 */
#define client_error_req(recv_buffer)	\
	while(1){	\
		if(Parity_Check(recv_buffer) == RIGHT){		\
			sendto(server_id, "OK", sizeof("OK"), 0, (struct sockaddr *)&sock_server, sizeof(sock_server));	\
			break;	\
		}	\
		sleep(1);	\
		printf("数据错误 准备接收重传\r\n");	\
		sendto(server_id, "ERROR", sizeof("ERROR"), 0, (struct sockaddr *)&sock_server, sizeof(sock_server));	\
		recvfrom(server_id, recv_buffer, sizeof(recv_buffer), 0, (struct sockaddr *)&sock_server, &s_len);	\
	}
	
/*	
 *	Describe：服务器发送差错重传
 *	@recv_buffer : 错误信息接收到这里
 *	@SRC : 如果错误重发什么
 */
#define server_error_resend(recv_buffer, SRC)	\
	while(1){	\
		recvfrom(server_id, recv_buffer, sizeof(recv_buffer), 0, (struct sockaddr *)&sock_client, &c_len);	\
		printf("recv_buf = %s\r\n", recv_buffer);	\
		if(strcmp(recv_buffer, "OK") == 0)	break;	\
		printf("数据错误 准备发送重传\r\n");	\
		sendto(server_id, &SRC, sizeof(SRC), 0, (struct sockaddr *)&sock_client, sizeof(sock_client));	\
	}
	
/*	
 *	Describe：客户端发送差错重传
 *	@recv_buffer : 错误信息接收到这里
 *	@SRC : 如果错误重发什么
 */
#define client_error_resend(recv_buffer, SRC)	\
	while(1){	\
		recvfrom(server_id, recv_buffer, sizeof(recv_buffer), 0, (struct sockaddr *)&sock_server, &s_len);	\
		printf("recv_buf = %s\r\n", recv_buffer);	\
		if(strcmp(recv_buffer, "OK") == 0)	break;		\
		printf("数据错误 准备发送重传\r\n");	\
		sendto(server_id, &SRC, sizeof(SRC), 0, (struct sockaddr *)&sock_server, sizeof(sock_server));	\
	}
	
/*	从客户端接收	*/
#define recv_from_client(recv_buffer)	\
	recvfrom(server_id, recv_buffer, sizeof(recv_buffer), 0, (struct sockaddr *)&sock_client, &c_len);	

/*	从服务器接收	*/
#define recv_from_server(recv_buffer)	\
	recvfrom(server_id, recv_buffer, sizeof(recv_buffer), 0, (struct sockaddr *)&sock_server, &s_len);	
	
/*	发送至客户端	- src为data数据包*/
#define send_to_server(src)	\
	sendto(server_id, &src, sizeof(src), 0, (struct sockaddr *)&sock_server, sizeof(sock_server));

/* 发送至服务器- src为data数据包 */
#define send_to_client(src)	\
	sendto(server_id, &src, sizeof(src), 0, (struct sockaddr *)&sock_client, sizeof(sock_client));

/*================================================================
*   Describe : 初始化data数据包
------------------------------------------------------------------
*	parameter	:
*	@Data	:	要初始化的数据包	
*	@seq_data	:	结构体seq值
*	@ack_data	:	结构体ack值
*	@check_data	:	结构体check值
*	@data_data	:	结构体my_data值
================================================================*/
#define data_init(Data, seq_data, ack_data, check_data, data_data)	\
	Data.seq = seq_data;	\
	Data.ack = ack_data;	\
	Data.check = check_data;	\
	strcpy(Data.my_data, data_data);	\


/*================================================================
*   Describe : 打印data数据包
------------------------------------------------------------------
*	parameter	:
*	@Data	:	要初始化的数据包	
*	@seq_data	:	结构体seq值
*	@ack_data	:	结构体ack值
*	@check_data	:	结构体check值
*	@data_data	:	结构体my_data值
================================================================*/

#define show_data(recv, buf)	\
	data = (Datapack *)recv;	\
	printf("seq : %d\r\n", get_seq(recv));	\
	printf("ack : %d\r\n", get_ack(recv));	\
	printf("check : %d\r\n", get_check(recv));	\
	get_data(recv, buf);	\
	printf("my_data : %s\r\n", buf);	

#endif
